Skip to content

feat(cortex): MCP Streamable HTTP endpoint at /mcp (remote connector, Phase 1)#102

Merged
ApiliumDevTeam merged 13 commits into
mainfrom
feat/mcp-http-connector
Jun 23, 2026
Merged

feat(cortex): MCP Streamable HTTP endpoint at /mcp (remote connector, Phase 1)#102
ApiliumDevTeam merged 13 commits into
mainfrom
feat/mcp-http-connector

Conversation

@ApiliumDevTeam

Copy link
Copy Markdown
Contributor

Summary

Adds a remote MCP transport over HTTP so aingle's MCP server can be used as a remote connector by cloud clients (claude.ai, and — being MCP-standard — Codex/Cursor/etc.), not just locally over stdio.

  • Serves the existing AingleMcp (25 tools) + AppState over Streamable HTTP at /mcp, mounted on cortex's existing axum server (rmcp 1.7 StreamableHttpService). Same tools, same service:: layer — only the transport is new.
  • Bearer-token auth on /mcp (constant-time compare), with a deliberate safety gate: the route is only mounted when a token is configured (--mcp-http-token / AINGLE_MCP_HTTP_TOKEN) or --mcp-http-allow-anonymous is passed — never exposed unintentionally.
  • AINGLE_PUBLIC_HOST adds the deployment hostname(s) to rmcp's allowed_hosts (default is loopback-only, anti DNS-rebinding).
  • New cargo feature mcp-http (composes rmcp transport-streamable-http-server + server-side-http). Default build and mcp-without-mcp-http are unaffected.

Why

The classic stdio MCP server only works with local clients (Claude Desktop classic / Claude Code). Cloud clients use remote HTTP connectors. This is Phase 1 of the remote connector.

Test plan

  • cargo test -p aingle_cortex --features "mcp-http dag" — 188 lib + integration; 0 failures.
  • tests/mcp_http_integration.rs over real HTTP: no-auth → 401, wrong token → 401, correct token → 2xx + serverInfo; gating (no token) → 404 (route absent); anonymous mode → 2xx without auth.
  • Builds: mcp dag mcp-http, mcp dag, and default — all compile.
  • New code clippy-clean; rustfmt applied to changed files.

Notes / scope

  • claude.ai caveat: claude.ai's connector UI can't attach a static bearer header, so a secured claude.ai connection needs OAuth (Phase 2). Programmatic/curl/MCP-Inspector use works now with the bearer token; --mcp-http-allow-anonymous enables an (open, test-only) claude.ai connection.
  • Deployment artifacts (Docker/Caddy/DigitalOcean) live in a separate private ops repo, not here.
  • Out of scope (Phase 2): OAuth 2.x / IdP.

ApiliumDevTeam and others added 13 commits June 22, 2026 23:36
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
… JWT accept/reject)

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…ource

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…-https JWKS

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@ApiliumDevTeam

Copy link
Copy Markdown
Contributor Author

Phase 2 added: OAuth 2.0 Resource Server

This PR now also includes Phase 2 — cortex acts as an OAuth Resource Server for /mcp, so cloud clients (claude.ai) can connect securely (the /mcp stdio→HTTP work was Phase 1).

What's new (feature mcp-oauth, extends mcp-http):

  • GET /.well-known/oauth-protected-resource (RFC 9728); 401 on /mcp returns WWW-Authenticate: Bearer resource_metadata="…" so clients discover the authorization server.
  • /mcp accepts a Bearer JWT validated against the issuer's JWKS: RS256 pinned, iss/aud/exp required (a token missing aud/iss is rejected), JWKS refresh rate-limited (anti-DoS), single reqwest client.
  • IdP-agnostic (issuer/JWKS/resource via config) — works with Keycloak, Auth0, etc. The Phase-1 static bearer still works alongside OAuth.
  • A focused adversarial security review ran on the validator; two Important findings (missing-claim acceptance bypass; unbounded JWKS-refresh DoS) were fixed and covered by tests.

Verification: all four feature combos compile (mcp-oauth / mcp-http / mcp / default); 242 tests pass, 0 failures, including a new OAuth integration test (local JWKS server → metadata 200, no-token 401+challenge, valid-JWT 2xx+serverInfo, wrong-aud 401) and 7 unit tests for the validator. New code is clippy-clean.

Out of scope: the Authorization Server (Keycloak), deployment, and secrets live in the private ops repo, not here.

@ApiliumDevTeam ApiliumDevTeam merged commit db653b3 into main Jun 23, 2026
20 of 21 checks passed
ApiliumDevTeam added a commit that referenced this pull request Jun 23, 2026
feat(cortex): MCP Streamable HTTP endpoint at /mcp (remote connector, Phase 1)
@ApiliumDevTeam ApiliumDevTeam deleted the feat/mcp-http-connector branch June 23, 2026 17:03
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant